package com.rui.study.test.ehcache.configuration;

import lombok.Getter;
import lombok.Setter;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;

import javax.sql.DataSource;

import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;

@Configuration
public class MultiDataSourceConfiguration {

    @Getter
    @Setter
    class DBProperties {
        String url;
        String driverClassName;
        String username;
        String password;
    }

    @Bean("plainDBProperties")
//    @RefreshScope
    @ConditionalOnProperty(prefix = "spring.datasource",
            name = {"url", "username", "password", "driver-class-name"})
    @ConfigurationProperties(prefix = "spring.datasource")
    public DBProperties plainDBProperties() {
        return new DBProperties();
    }

    @Bean("serviceDBProperties")
//    @RefreshScope
    @ConditionalOnProperty(prefix = "spring.datasource.service",
            name = {"url", "username", "password", "driver-class-name"})
    @ConfigurationProperties(prefix = "spring.datasource.service")
    public DBProperties serviceDBProperties() {
        return new DBProperties();
    }

    @Bean("plainDataSource")
//    @RefreshScope
    @ConditionalOnBean(value = DBProperties.class, name = "plainDBProperties")
    public DataSource plainDataSource(@Qualifier("plainDBProperties") DBProperties dbProperties) {
        return DataSourceBuilder.create()
                .url(dbProperties.getUrl())
                .driverClassName(dbProperties.getDriverClassName())
                .username(dbProperties.getUsername())
                .password(dbProperties.getPassword())
                .build();
    }

    @Bean("serviceDataSource")
//    @RefreshScope
    @Primary
    @ConditionalOnBean(value = DBProperties.class, name = "serviceDBProperties")
    public DataSource serviceDataSource(@Qualifier("serviceDBProperties") DBProperties dbProperties) {
        return DataSourceBuilder.create()
                .url(dbProperties.getUrl())
                .driverClassName(dbProperties.getDriverClassName())
                .username(dbProperties.getUsername())
                .password(dbProperties.getPassword())
                .build();
    }

    /**
     * 建库脚本初始化
     * @param dataSource
     * @return
     */
    @Bean("plainDataSourceInitializer")
//    @RefreshScope
    @ConditionalOnBean(value = DataSource.class, name = "plainDataSource")
    public DataSourceInitializer plainDataSourceInitializer(
            @Qualifier("plainDataSource") DataSource dataSource) {
        return buildDataSourceInitializer("schema.sql", dataSource);
    }

    /**
     * 建表脚本初始化
     * @param dataSource
     * @return
     */
    @Bean("serviceDataSourceInitializer")
//    @RefreshScope
    @ConditionalOnBean(value = DataSource.class, name = "serviceDataSource")
    public DataSourceInitializer serviceDataSourceInitializer(
            @Qualifier("serviceDataSource") DataSource dataSource) {
        return buildDataSourceInitializer("table.sql", dataSource);
    }

    private DataSourceInitializer buildDataSourceInitializer(String scriptName, DataSource dataSource) {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource resource = resolver.getResource("classpath:" + scriptName);
        if (!resource.exists()) {
            return null;
        }

        ResourceDatabasePopulator populator = new ResourceDatabasePopulator(resource);
        populator.setSqlScriptEncoding("utf-8");

        DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource);
        initializer.setDatabasePopulator(populator);

        return initializer;
    }


    @Bean
    @ConditionalOnBean(value = DataSource.class, name = "serviceDataSource")
    public SqlSessionFactory sqlSessionFactofy(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
//        bean.setMapperLocations(resolver.getResources("classpath:/mybatis-mappers/*-mapper.xml"));
        bean.setMapperLocations(resolver.getResources(CLASSPATH_ALL_URL_PREFIX + "/**/*-mapper.xml"));

        return bean.getObject();
    }
}
